// Basic behaviours
//--------------------------------
#ifndef BBASIC_H
#define BBASIC_H
#include "behaviour.h"
#include "symbol.h"
#include "io.h"

// Called to find the item object of a
// physical representation of an item
// Param item - item pointer return
class BIIsActor : public BIConst< Actor** > {
public:

    BEHAVIOUR_CALL const
    {
        return IsActor( a0 );
    }

    BEHAVIOUR_START
    {
        *a0 = 0;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool IsActor( Actor** actor ) const = 0;

};

// Called to find out if remember position
// Param item - item pointer return
class BIMemorySymbol : public BIConst< bool*, bool* > {
public:

    BEHAVIOUR_CALL const
    {
        return MemorySymbol( a0, a1 );
    }

    BEHAVIOUR_START
    {
        *a0 = false;
        *a1 = false;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool MemorySymbol( bool* memory, bool* tileMemory ) const = 0;

};

// Called to find the item object of a
// physical representation of an item
// Param item - item pointer return
class BIPriority : public BIConst< int* > {
public:

    BEHAVIOUR_CALL const
    {
        return Priority( a0 );
    }

    BEHAVIOUR_START
    {
        *a0 = 0;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool Priority( int* priority ) const = 0;

};

// Called to find whether an actor is blocking
// Param blocking - blocks pathing return value
// Param losBlocking - blocks line of sight return value
// Param pushType - push through or displace
class BIBlocking : public BIConst< bool*, bool*, uint* > {
public:

    enum PushType {
        PUSH_NONE,
        PUSH_DISPLACE,
        PUSH_MOVE
    };

    BEHAVIOUR_CALL const
    {
        return Blocking( a0, a1, a2 );
    }

    BEHAVIOUR_START
    {
        *a0 = false;
        *a1 = false;
        *a2 = PUSH_NONE;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool Blocking( bool* blocking, bool* losBlocking, uint* pushType ) const = 0;

};

// Called to find symbol of an actor
// Param symbol - return value for symbol
// Param colour - return value for colour
class BISymbol : public BIConst< IO::SymList* > {
public:

    BEHAVIOUR_CALL const
    {
        return Symbol( a0 );
    }

    BEHAVIOUR_START
    {
        a0->clear();
    }
    BEHAVIOUR_END { }

protected:

    virtual bool Symbol( IO::SymList* list ) const = 0;

};

// Called to find speed of an actor
// Param speed - return value in ticks per action. Initialise to zero
class BISpeed : public BIConst< int* > {
public:

    BEHAVIOUR_CALL const
    {
        return Speed( a0 );
    }

    BEHAVIOUR_START
    {
        *a0 = 0;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool Speed( int* speed ) const = 0;

};

// Called to find name of an actor
// Param name - return value
class BIName : public BIConst< std::string*, bool*, uint > {
public:

    BEHAVIOUR_CALL const
    {
        return Name( a0, a1, a2 );
    }

    BEHAVIOUR_START
    {
        *a0 = "";
        *a1 = a2 == ARTICLE_PLURAL;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool Name( std::string* name, bool* plural, uint article ) const = 0;

};

// Called to check if an actor is invisible
// Param invisible - return value
class BIInvisible : public BIConst< bool* > {
public:

    BEHAVIOUR_CALL const
    {
        return Invisible( a0 );
    }

    BEHAVIOUR_START
    {
        *a0 = false;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool Invisible( bool* invisible ) const = 0;

};

// Called every tick, before any action that may take place
class BIOnTick : public BI<> {
public:

    BEHAVIOUR_CALL
    {
        return OnTick();
    }

    BEHAVIOUR_START { }
    BEHAVIOUR_END { }

protected:

    virtual bool OnTick() = 0;

};

// Called every action
// Param speed - returns the speed modifier of the taken action
class BIOnAction : public BI< int* > {
public:

    BEHAVIOUR_CALL
    {
        return OnAction( a0 );
    }

    BEHAVIOUR_START
    {
        *a0 = 0;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool OnAction( int* speedMod ) = 0;

};

// Called when an actor attempts to move
// Param direction - direction as given by numpad
// Param moved     - whether movement happened
class BIOnMove : public BI< uint*, bool* > {
public:

    BEHAVIOUR_CALL
    {
        return OnMove( a0, a1 );
    }

    BEHAVIOUR_START
    {
        *a1 = false;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool OnMove( uint* direction, bool* moved ) = 0;

};

// Called when an actor is pushed by another
// Param source  - source actor
// Param pushed  - whether pushthrough happened
// Param reverse - pulling instead
// Param first   - whether this is the first in the row
class BIOnPushed : public BI< Actor*, bool, bool*, bool > {
public:

    BEHAVIOUR_CALL
    {
        return OnPushed( a0, a1, a2, a3 );
    }

    BEHAVIOUR_START
    {
        *a2 = false;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool OnPushed( Actor* source, bool reverse, bool* pushed, bool first ) = 0;

};

#endif
